import java.io.IOException;

import javax.xml.bind.JAXBException;

import java.awt.FileDialog;
import java.awt.Frame;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import javax.xml.bind.JAXBException;
import processing.core.PApplet;
import processing.core.PFont;
import save.xml.jaxb.Interface;

@SuppressWarnings("serial")
public class Main extends PApplet {

	// *------ INTERFACE ----------*
	// Key keyListener = new Key();
	boolean loaded = false;
	static boolean editMode = false;
	boolean appleBtn = false;
	boolean shift = false;
	boolean caps = false;
	boolean option = false;
	boolean resizeSel = false;
	boolean renameMode = false;
	boolean anythingPressed = false;
	boolean dragging = false;
	boolean massSelection = false;
	int[] selection = new int[4];
	PFont f;
	static button[] buttons = new button[0];
	static graph[] graphs = new graph[0];
	static radial[] radials = new radial[0];
	int row1 = 50;
	int col1 = 100;
	int b1_w = 100;
	int b1_h = 50;
	int b1_VS = 20 + b1_h;
	int b1_HS = 20 + b1_w;
	int s1_w = 100;
	int s1_h = 100;
	int r1_w = 70;
	int r1_h = 70;
	int s1_VS = 50 + s1_h;
	int s1_HS = 20 + b1_w;
	int[] params = new int[4];
	int locationX = 0;
	int locationY = 0;

	String name = "default";
	Interface _interface = new Interface();

	// // *------ MUSIC ----------*
	public static XML xml = new XML();
	public static Statistics stats = new Statistics();
	public static TextGUI textGUI = new TextGUI();

	public static int[][] noteOut = new int[3][]; // notes 'to be played' each
	// bar

	public static int[][] pchIn = new int[1][0]; // bar-arrays of pitches
	public static int[][] rhyIn = new int[1][0]; // bar-arrays of onsets
	public static int[][] velIn = new int[1][0]; // bar-arrays of pitches

	public static int bpm = 130;
	public static int velocity = 70;
	public static MidiIn midiIn = new MidiIn();

	public static boolean stop = true;

	public static int count = 0;

	public static boolean humanPlaying = false;

	public static boolean playing = false;

	public static int lastInClk = 0;
	public static int timeDiff = 0;

	public static void main(String args[]) {
		PApplet.main(new String[] { "Main" });
	}

	// all non interface related initialization
	public void init_() {
		try {
			xml.init();
		} catch (JAXBException e1) {
			e1.printStackTrace();
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		OSCin.run();

		PositionArms pos = new PositionArms();
		Thread posThread = new Thread(pos);
		posThread.start();

		TurnTaking turnTaking = new TurnTaking();
		Thread turnThread = new Thread(turnTaking);
		turnThread.start();

	}

	// this is called once at the beginning of running
	public void setup() {
		init_();

		frame.setResizable(true);
		textFont(createFont("SansSerif", (int) (12)));

		smooth();
		background(255);
	}

	// this function is called regularly ~30/s
	public void draw() {

		if (!loaded) {

			try {
				String path = new java.io.File(".").getCanonicalPath();
				println(path + "/" + name + ".xml");
				File f = new File(path + "/" + name);
				if (f.exists()) {
					load(name);
				} else {
					println("FALSE");
				}
			} catch (IOException e) {
				e.printStackTrace();
			}

			loaded = true;
		}
		if (editMode) {
			background(245);
			fill(0);
			text("-- edit mode --", width / 2 - 45, 50);
		} else {
			background(255);
		}
		updateButtons(buttons);
		updateGraphs(graphs);
		updateRadials(radials);
		if (editMode) {
			selectionBox();
		}
	}

	public void keyPressed() { // key press shortcuts
		println(keyCode);
		if (keyCode == 76 && appleBtn) { // load interface
			FileDialog fd;
			Frame f = new Frame();
			buttons = new button[0];
			graphs = new graph[0];
			radials = new radial[0];
			// open a file
			fd = new FileDialog(f, "Input file name or choose cancel to"
					+ " finish.", FileDialog.LOAD);
			String path;
			try {
				path = new java.io.File(".").getCanonicalPath();
				fd.setDirectory(path);
			} catch (IOException e2) {
				e2.printStackTrace();
			}
			fd.setVisible(true);

			// break out when user presses cancel
			if (fd.getFile() != null) {
				load(fd.getFile());
			}
		}

		if (keyCode == 83 && appleBtn && !editMode) { // save interface
			FileDialog fd;
			Frame f = new Frame();

			// open a file
			fd = new FileDialog(f, "Input file name or choose cancel to"
					+ " finish.", FileDialog.SAVE);
			String path;
			try {
				path = new java.io.File(".").getCanonicalPath();
				fd.setDirectory(path);
			} catch (IOException e2) {
				e2.printStackTrace();
			}
			fd.setVisible(true);

			// break out when user presses cancel
			if (fd.getFile() != null) {
				name = (fd.getFile());
				println(name);

				try {
					xml.newInterface(name);
				} catch (JAXBException e1) {
					e1.printStackTrace();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
				xml.setWidth(width);
				xml.setHeight(height);
				xml.setLocationX(frame.getLocation().x);
				xml.setLocationY(frame.getLocation().y);
				Object[][] buttonsObj = new Object[buttons.length][];
				for (int i = 0; i < buttons.length; i++) {
					buttonsObj[i] = buttons[i].toObj();
				}
				xml.setButtons(buttonsObj);
				Object[][] graphsObj = new Object[graphs.length][];
				System.out.println("graphs.length: " + graphs.length);
				for (int i = 0; i < graphs.length; i++) {
					graphsObj[i] = graphs[i].toObj();
				}
				xml.setGraphs(graphsObj);
				println("before radials");
				Object[][] radialsObj = new Object[radials.length][];
				System.out.println("radials.length: " + radials.length);
				for (int i = 0; i < radials.length; i++) {
					radialsObj[i] = radials[i].toObj();
				}
				xml.setRadials(radialsObj);
				println("after radials");
				try {
					xml.writeInterface();
				} catch (JAXBException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		if (keyCode == 157) {
			appleBtn = true;
		}
		if ((keyCode == 87 || keyCode == 81) && appleBtn) {
			System.exit(0);
		}
		if (keyCode == 16) {
			shift = true;
		}
		if (keyCode == 18) {
			option = true;
		}
		if (keyCode == 20) {
			if (caps) {
				caps = false;
			} else {
				caps = true;
			}
		}
		if (!renameMode) { // only listen to these key presses if you are not
							// labeling an object

			if (appleBtn && keyCode == 65) { // select all with 'apple-a'
				for (int i = 0; i < buttons.length; i++) {
					buttons[i].selected = true;
				}
				for (int i = 0; i < graphs.length; i++) {
					graphs[i].selected = true;
				}
				for (int i = 0; i < radials.length; i++) {
					radials[i].selected = true;
				}
			}
			if (keyCode >= 37 && keyCode <= 40) { // directional keys to move
													// selected objects
				int moveSize = 2;
				for (int i = 0; i < buttons.length; i++) {
					if (editMode) {
						if (buttons[i].selected) {

							switch (keyCode) {
							case (37): // left
								buttons[i].x -= moveSize;
								break;
							case (38): // up
								buttons[i].y -= moveSize;
								break;
							case (39): // right
								buttons[i].x += moveSize;
								break;
							case (40): // down
								buttons[i].y += moveSize;
								break;

							}
						}
					}
				}
				for (int i = 0; i < graphs.length; i++) {
					if (editMode) {
						if (graphs[i].selected) {
							switch (keyCode) {
							case (37): // left
								graphs[i].x -= moveSize;
								break;
							case (38): // up
								graphs[i].y -= moveSize;
								break;
							case (39): // right
								graphs[i].x += moveSize;
								break;
							case (40): // down
								graphs[i].y += moveSize;
								break;

							}
						}
					}
				}
				for (int i = 0; i < radials.length; i++) {
					if (editMode) {
						if (radials[i].selected) {
							switch (keyCode) {
							case (37): // left
								radials[i].x -= moveSize;
								break;
							case (38): // up
								radials[i].y -= moveSize;
								break;
							case (39): // right
								radials[i].x += moveSize;
								break;
							case (40): // down
								radials[i].y += moveSize;
								break;

							}
						}
					}
				}
			}
			if (keyCode == 8) { // delete with 'backspace'
				button[] tempButtons = new button[buttons.length];
				int buttonPointer = 0;
				for (int i = 0; i < buttons.length; i++) {
					if (!buttons[i].selected) {
						tempButtons[buttonPointer] = new button(this);
						tempButtons[buttonPointer].init(buttons[i].x,
								buttons[i].y, buttons[i].w, buttons[i].h,
								buttons[i].label, buttons[i].toggle);
						buttonPointer++;
					}
				}
				buttons = new button[buttonPointer];
				for (int i = 0; i < buttons.length; i++) {
					buttons[i] = new button(this);
					buttons[i].init(tempButtons[i].x, tempButtons[i].y,
							tempButtons[i].w, tempButtons[i].h,
							tempButtons[i].label, tempButtons[i].toggle);
				}

				graph[] tempGraphs = new graph[graphs.length];
				int graphPointer = 0;
				for (int i = 0; i < graphs.length; i++) {
					if (!graphs[i].selected) {
						tempGraphs[graphPointer] = new graph(this);
						tempGraphs[graphPointer].init(graphs[i].x, graphs[i].y,
								graphs[i].w, graphs[i].h, graphs[i].label,
								graphs[i].showValues, i);
						tempGraphs[graphPointer]._x = graphs[i]._x;
						tempGraphs[graphPointer]._y = graphs[i]._y;
						graphPointer++;
					}
				}
				graphs = new graph[graphPointer];
				for (int i = 0; i < graphs.length; i++) {
					graphs[i] = new graph(this);
					graphs[i].init(tempGraphs[i].x, tempGraphs[i].y,
							tempGraphs[i].w, tempGraphs[i].h,
							tempGraphs[i].label, tempGraphs[i].showValues, i);
					graphs[i]._x = tempGraphs[i]._x;
					graphs[i]._y = tempGraphs[i]._y;
				}
				radial[] tempRadials = new radial[radials.length];
				int radialPointer = 0;
				for (int i = 0; i < radials.length; i++) {
					if (!radials[i].selected) {
						tempRadials[radialPointer] = new radial(this);
						tempRadials[radialPointer].init(radials[i].x,
								radials[i].y, radials[i].w, radials[i].h,
								radials[i].label, radials[i].showValues, i);
						tempRadials[radialPointer].degree = radials[i].degree;
						radialPointer++;
					}
				}

				radials = new radial[radialPointer];
				for (int i = 0; i < radials.length; i++) {
					radials[i] = new radial(this);
					radials[i].init(tempRadials[i].x, tempRadials[i].y,
							tempRadials[i].w, tempRadials[i].h,
							tempRadials[i].label, tempRadials[i].showValues, i);
					radials[i].degree = tempRadials[i].degree;
				}
			}
			if (keyCode == 89) {
				// println("Anything pressed? "+anythingPressed);
			}
			if (keyCode == 89 && appleBtn) { // alignment
				int leftMost = width; // will align to leftest object
				int highest = height; // will align to highest object
				int rightMost = 0; // calculate the horizontal and vertical
									// difference
				int lowest = 0; // whichever is bigger, align to that axis
				boolean alignVert = true; // should it align to vertical axis?
				for (int i = 0; i < buttons.length; i++) {
					if (buttons[i].selected) {
						if (buttons[i].x < leftMost) {
							leftMost = buttons[i].x;
						}
						if (buttons[i].x > rightMost) {
							rightMost = buttons[i].x;
						}
						if (buttons[i].y < highest) {
							highest = buttons[i].y;
						}
						if (buttons[i].y > lowest) {
							lowest = buttons[i].y;
						}
					}
				}
				for (int i = 0; i < graphs.length; i++) {
					if (graphs[i].selected) {
						if (graphs[i].x < leftMost) {
							leftMost = graphs[i].x;
						}
						if (graphs[i].x > rightMost) {
							rightMost = graphs[i].x;
						}
						if (graphs[i].y < highest) {
							highest = graphs[i].y;
						}
						if (graphs[i].y > lowest) {
							lowest = graphs[i].y;
						}
					}
				}

				for (int i = 0; i < radials.length; i++) {
					if (radials[i].selected) {
						if (radials[i].x < leftMost) {
							leftMost = radials[i].x - radials[i].w / 2;
						}
						if (radials[i].x > rightMost) {
							rightMost = radials[i].x - radials[i].w / 2;
						}
						if (radials[i].y < highest) {
							highest = radials[i].y - radials[i].h / 2;
						}
						if (radials[i].y > lowest) {
							lowest = radials[i].y - radials[i].h / 2;
						}
					}
				}
				if (rightMost - leftMost > lowest - highest) {
					alignVert = false;
				}
				System.out.println("leftMost = " + leftMost + " rightMost = "
						+ rightMost + " lowest = " + lowest + " highest = "
						+ highest);
				for (int i = 0; i < buttons.length; i++) {
					if (buttons[i].selected) {
						if (alignVert) {
							buttons[i].x = leftMost;
						} else {
							buttons[i].y = highest;
						}
					}
				}
				for (int i = 0; i < graphs.length; i++) {
					if (graphs[i].selected) {
						if (alignVert) {
							graphs[i].x = leftMost;
						} else {
							graphs[i].y = highest;
						}
					}
				}
				for (int i = 0; i < radials.length; i++) {
					if (radials[i].selected) {
						if (alignVert) {
							radials[i].x = leftMost + radials[i].w / 2;
						} else {
							radials[i].y = highest + radials[i].h / 2;
						}
					}
				}
			}

			if (keyCode == 84 && editMode) { // make toggle button with 't'
				buttons = AltMath.incArray(buttons);
				buttons[buttons.length - 1] = new button(this);
				buttons[buttons.length - 1].init(mouseX, mouseY, b1_w, b1_h,
						"default", true);
			}
			if (keyCode == 66 && editMode) { // make button with 'b'
				buttons = AltMath.incArray(buttons);
				buttons[buttons.length - 1] = new button(this);
				buttons[buttons.length - 1].init(mouseX, mouseY, b1_w, b1_h,
						"default", false);
			}

			if (keyCode == 83 && editMode && !appleBtn) { // make slider with
															// 's'
				graphs = AltMath.incArray(graphs);
				graphs[graphs.length - 1] = new graph(this);
				graphs[graphs.length - 1].init(mouseX, mouseY, 0, s1_h,
						"default", true, graphs.length - 1);
			}

			if (keyCode == 71 && editMode) { // make graph with 'g'
				graphs = AltMath.incArray(graphs);
				graphs[graphs.length - 1] = new graph(this);
				graphs[graphs.length - 1].init(mouseX, mouseY, s1_w, s1_h,
						"default", true, graphs.length - 1);
			}

			if (keyCode == 82 && editMode && !appleBtn) { // make radial with
															// 'r'
				radials = AltMath.incArray(radials);
				radials[radials.length - 1] = new radial(this);
				radials[radials.length - 1].init(mouseX, mouseY, r1_w, r1_h,
						"default", true, radials.length - 1);
			}

			if (keyCode == 78 && editMode) { // set rename mode with 'n'
				for (int i = 0; i < buttons.length; i++) {
					if (buttons[i].selected) {
						renameMode = true;
						buttons[i].rename = true;
						buttons[i].label = "";
					}
				}
				for (int i = 0; i < graphs.length; i++) {
					if (graphs[i].selected) {
						renameMode = true;
						graphs[i].rename = true;
						graphs[i].label = "";
					}
				}
				for (int i = 0; i < radials.length; i++) {
					if (radials[i].selected) {
						renameMode = true;
						radials[i].rename = true;
						radials[i].label = "";
					}
				}
			}
			if (keyCode == 69 && appleBtn) {
				if (editMode) {
					editMode = false;
					println("edit mode off");
				} else {
					editMode = true;
					println("edit mode on!");
				}
			}

		} else {
			if (keyCode == 10) { // press 'enter' to end renaming
				renameMode = false;
				for (int i = 0; i < buttons.length; i++) {
					if (buttons[i].rename) {
						buttons[i].rename = false;
						buttons[i].selected = false;
					}
				}
				for (int i = 0; i < graphs.length; i++) {
					if (graphs[i].rename) {
						graphs[i].rename = false;
						graphs[i].selected = false;
					}
				}
				for (int i = 0; i < radials.length; i++) {
					if (radials[i].rename) {
						radials[i].rename = false;
						radials[i].selected = false;
					}
				}
			} else {
				for (int i = 0; i < buttons.length; i++) {
					if (buttons[i].rename) {
						if (caps || shift || keyCode < 65 || keyCode > 96) {
							if (keyCode == 8) {
								if (buttons[i].label.length() <= 1) {
									buttons[i].label = "";
								} else {
									buttons[i].label = buttons[i].label
											.substring(0, buttons[i].label
													.length() - 1);
								}
							} else if (keyCode == 16) { // don't add shift as a
														// character

							} else {
								buttons[i].label = (buttons[i].label + (char) (keyCode));
							}
						} else {
							buttons[i].label = (buttons[i].label + (char) (keyCode + 32));
						}
					}
				}
				for (int i = 0; i < graphs.length; i++) {
					if (graphs[i].rename) {
						if (caps || shift || keyCode < 65 || keyCode > 96) {
							if (keyCode == 8) { // backspace a letter
								if (graphs[i].label.length() <= 1) {
									graphs[i].label = "";
								} else {
									graphs[i].label = graphs[i].label
											.substring(0, graphs[i].label
													.length() - 1);
								}
							} else if (keyCode == 16) { // don't add shift as a
														// character

							} else {
								graphs[i].label = (graphs[i].label + (char) (keyCode));
							}
						} else {
							graphs[i].label = (graphs[i].label + (char) (keyCode + 32));
						}
					}
				}
				for (int i = 0; i < radials.length; i++) {
					if (radials[i].rename) {
						if (caps || shift || keyCode < 65 || keyCode > 96) {
							if (keyCode == 8) {
								if (radials[i].label.length() <= 1) {
									radials[i].label = "";
								} else {
									radials[i].label = radials[i].label
											.substring(0, radials[i].label
													.length() - 1);
								}
							} else {
								radials[i].label = (radials[i].label + (char) (keyCode));
							}
						} else {
							radials[i].label = (radials[i].label + (char) (keyCode + 32));
						}
					}
				}
			}
		}
	}

	public void load(String filename) { // load an interface
		try {
			xml.newInterface(filename);
		} catch (JAXBException e1) {
			e1.printStackTrace();
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		try {
			frame.setSize(XML.getWidth(filename), XML.getHeight(filename));
			frame.setLocation(XML.getLocationX(filename), XML
					.getLocationY(filename));
			Object[][] buttonsObj = XML.getButtons(filename);
			if (buttonsObj != null) {
				buttons = new button[buttonsObj.length];
				for (int i = 0; i < buttons.length; i++) {
					buttons[i] = new button(this);
					buttons[i].init((Integer) buttonsObj[i][0],
							(Integer) buttonsObj[i][1],
							(Integer) buttonsObj[i][2],
							(Integer) buttonsObj[i][3],
							(String) buttonsObj[i][9],
							(Boolean) buttonsObj[i][11],
							(Boolean) buttonsObj[i][10]);
					UIActions.buttonAction(i);
				}
			}
			Object[][] graphsObj = XML.getGraphs(filename);
			if (graphsObj != null) {
				graphs = new graph[graphsObj.length];
				for (int i = 0; i < graphs.length; i++) {
					graphs[i] = new graph(this);
					graphs[i].init((Integer) graphsObj[i][1],
							(Integer) graphsObj[i][2],
							(Integer) graphsObj[i][3],
							(Integer) graphsObj[i][4],
							(String) graphsObj[i][15],
							(Boolean) graphsObj[i][16],
							(Integer) graphsObj[i][0],
							(Integer) graphsObj[i][5],
							(Integer) graphsObj[i][6]);
					UIActions.graphAction(i);
				}
			}
			Object[][] radialsObj = XML.getRadials(filename);
			if (radialsObj != null) {
				radials = new radial[radialsObj.length];
				for (int i = 0; i < radials.length; i++) {
					radials[i] = new radial(this);
					radials[i].init((Integer) radialsObj[i][1],
							(Integer) radialsObj[i][2],
							(Integer) radialsObj[i][3],
							(Integer) radialsObj[i][4],
							(String) radialsObj[i][12],
							(Boolean) radialsObj[i][13],
							(Integer) radialsObj[i][0],
							(Integer) radialsObj[i][5]);
					UIActions.radialAction(i);
				}
			}
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
		} catch (JAXBException e1) {
			e1.printStackTrace();
		}

	}

	public void keyReleased() {
		if (keyCode == 18) {
			option = false;
		}
		if (keyCode == 157) {
			appleBtn = false;
		}
		if (keyCode == 16) {
			shift = false;
		}
	}

	void selectionBox() {
		if (!anythingPressed && mousePressed) { // then create
			massSelection = true;
			if (selection[0] > mouseX) {
				params[0] = mouseX;
				params[2] = selection[0] - mouseX;
			} else {
				params[0] = selection[0];
				params[2] = mouseX - selection[0];
			}
			if (selection[1] > mouseY) {
				params[1] = mouseY;
				params[3] = selection[1] - mouseY;
			} else {
				params[1] = selection[1];
				params[3] = mouseY - selection[1];
			}
			fill(0, 0, 0, 10);
			rect(params[0], params[1], params[2], params[3]);

			for (int i = 0; i < buttons.length; i++) {
				buttons[i].rename = false;
				if ((params[0] < buttons[i].x + buttons[i].w && params[2]
						+ params[0] >= buttons[i].x)
						&& (params[1] < buttons[i].y + buttons[i].h && params[3]
								+ params[1] >= buttons[i].y)) {
					buttons[i].selected = true;
					buttons[i].display();
				} else {
					if (buttons[i].selected && !shift) {
						buttons[i].selected = false;
						buttons[i].display();
					}
				}
			}

			for (int i = 0; i < graphs.length; i++) {
				graphs[i].rename = false;
				if ((params[0] < graphs[i].x + graphs[i].w && params[2]
						+ params[0] >= graphs[i].x)
						&& (params[1] < graphs[i].y + graphs[i].h && params[3]
								+ params[1] >= graphs[i].y)) {
					graphs[i].selected = true;
					graphs[i].display();
				} else {
					if (graphs[i].selected && !shift) {
						graphs[i].selected = false;
						graphs[i].display();
					}
				}
			}

			for (int i = 0; i < radials.length; i++) {
				radials[i].rename = false;
				if ((params[0] < radials[i].x + radials[i].w && params[2]
						+ params[0] >= radials[i].x)
						&& (params[1] < radials[i].y + radials[i].h && params[3]
								+ params[1] >= radials[i].y)) {
					radials[i].selected = true;
					radials[i].display();
				} else {
					if (radials[i].selected && !shift) {
						radials[i].selected = false;
						radials[i].display();
					}
				}
			}
		}
	}

	public int bounded(int dimension) {
		if (dimension < 0) {
			dimension = 0;
		}
		return dimension;
	}

	public void mouseDragged() {
		if (anythingPressed) {
			for (int i = 0; i < buttons.length; i++) {
				if (editMode) {
					if (buttons[i].resizeSel) {
						buttons[i].w = bounded(buttons[i].w + mouseX - pmouseX);
						buttons[i].h = bounded(buttons[i].h + mouseY - pmouseY);
					} else if (buttons[i].selected) {
						buttons[i].x += (mouseX - pmouseX);
						buttons[i].y += (mouseY - pmouseY);
					}
				}
				buttons[i].display();
			}
			for (int i = 0; i < graphs.length; i++) {
				if (editMode) {
					if (graphs[i].resizeSel) {
						graphs[i].w = bounded(graphs[i].w + mouseX - pmouseX);
						graphs[i].h = bounded(graphs[i].h + mouseY - pmouseY);
					} else if (graphs[i].selected) {
						graphs[i].x += (mouseX - pmouseX);
						graphs[i].y += (mouseY - pmouseY);
					}
				} else if (graphs[i].selected) {
					// UIActions.graphAction(i);
				}
				graphs[i].display();
			}
			for (int i = 0; i < radials.length; i++) {
				if (editMode) {
					if (radials[i].resizeSel) {
						int alterSize = (bounded(radials[i].w + mouseX
								- pmouseX) + bounded(radials[i].h + mouseY
								- pmouseY)) / 2;
						radials[i].w = alterSize;
						radials[i].h = alterSize;
						;
					} else if (radials[i].selected) {
						radials[i].x += (mouseX - pmouseX);
						radials[i].y += (mouseY - pmouseY);
					}
				} else if (radials[i].selected) {
					// UIActions.radialAction(i);
				}
				radials[i].display();
			}
		}
	}

	public boolean stillMassSelection() {
		boolean still = true;
		anythingPressed = false;
		for (int i = 0; i < buttons.length; i++) {
			if (mouseX > buttons[i].x && mouseX < buttons[i].x + buttons[i].w
					&& mouseY > buttons[i].y
					&& mouseY < buttons[i].y + buttons[i].h) {
				anythingPressed = true;
				if (!buttons[i].selected) {
					still = false;
				}
			}
		}
		for (int i = 0; i < graphs.length; i++) {
			if (mouseX > graphs[i].x - graphs[i]._w / 2
					&& mouseX < graphs[i].x + graphs[i].w + graphs[i]._w / 2
					&& mouseY > graphs[i].y - graphs[i]._h / 2
					&& mouseY < graphs[i].y + graphs[i].h + graphs[i]._h / 2) {
				anythingPressed = true;
				if (!graphs[i].selected) {
					still = false;
				}
			}
		}
		for (int i = 0; i < radials.length; i++) {
			if (mouseX > radials[i].x - radials[i].w / 2
					&& mouseX < radials[i].x + radials[i].w / 2
					&& mouseY > radials[i].y - radials[i].h / 2
					&& mouseY < radials[i].y + radials[i].h / 2) {

				anythingPressed = true;
				if (!radials[i].selected) {
					still = false;
				}
			}
		}
		if (!anythingPressed) {
			still = false;
		}
		return still;
	}

	public boolean wasSel() {
		boolean selected = false;
		for (int i = 0; i < buttons.length; i++) {
			buttons[i].rename = false;
			if (mouseX > buttons[i].x && mouseX < buttons[i].x + buttons[i].w
					&& mouseY > buttons[i].y
					&& mouseY < buttons[i].y + buttons[i].h) {
				if (buttons[i].selected) {
					selected = true;
				}
			}
		}
		for (int i = 0; i < graphs.length; i++) {
			if (mouseX > graphs[i].x - graphs[i]._w / 2
					&& mouseX < graphs[i].x + graphs[i].w + graphs[i]._w / 2
					&& mouseY > graphs[i].y - graphs[i]._h / 2
					&& mouseY < graphs[i].y + graphs[i].h + graphs[i]._h / 2) {
				if (graphs[i].selected) {
					selected = true;
				}
			}
		}
		for (int i = 0; i < radials.length; i++) {
			radials[i].rename = false;
			if (mouseX > radials[i].x - radials[i].w / 2
					&& mouseX < radials[i].x + radials[i].w / 2
					&& mouseY > radials[i].y - radials[i].h / 2
					&& mouseY < radials[i].y + radials[i].h / 2) {
				if (radials[i].selected) {
					selected = true;
				}
			}
		}
		return selected;
	}

	public void mousePressed() {
		boolean wasSel = wasSel();
		if (massSelection) {
			println(massSelection + " " + wasSel);
			massSelection = stillMassSelection();
			int length = buttons.length;
			for (int i = 0; i < length; i++) {
				if (option && buttons[i].selected) {
					System.out.println("duplicate");
					buttons = AltMath.incArray(buttons);
					buttons[buttons.length - 1] = new button(this);
					buttons[buttons.length - 1].init(buttons[i].x,
							buttons[i].y, buttons[i].w, buttons[i].h,
							buttons[i].label, buttons[i].toggle);
					buttons[buttons.length - 1].selected = true;
					buttons[i].selected = false;
				} else {
					if (mouseX > buttons[i].x
							&& mouseX < buttons[i].x + buttons[i].w
							&& mouseY > buttons[i].y
							&& mouseY < buttons[i].y + buttons[i].h) {
						if (shift && buttons[i].selected) {
							buttons[i].selected = false;
						}
					}
				}
			}
			length = graphs.length;
			for (int i = 0; i < length; i++) {
				if (option && graphs[i].selected) {
					System.out.println("duplicate");
					graphs = AltMath.incArray(graphs);
					graphs[graphs.length - 1] = new graph(this);
					graphs[graphs.length - 1].init(graphs[i].x, graphs[i].y,
							graphs[i].w, graphs[i].h, graphs[i].label,
							graphs[i].showValues, i);
					graphs[graphs.length - 1].selected = true;
					graphs[i].selected = false;
				} else {
					if (mouseX > graphs[i].x - graphs[i]._w / 2
							&& mouseX < graphs[i].x + graphs[i].w
									+ graphs[i]._w / 2
							&& mouseY > graphs[i].y - graphs[i]._h / 2
							&& mouseY < graphs[i].y + graphs[i].h
									+ graphs[i]._h / 2) {
						if (shift && graphs[i].selected) {
							graphs[i].selected = false;
						}
					}
				}
			}
			length = radials.length;
			for (int i = 0; i < length; i++) {
				if (option && radials[i].selected) {
					radials = AltMath.incArray(radials);
					radials[radials.length - 1] = new radial(this);
					radials[radials.length - 1].init(radials[i].x,
							radials[i].y, radials[i].w, radials[i].h,
							radials[i].label, radials[i].showValues, i);
					radials[radials.length - 1].selected = true;
					radials[i].selected = false;
				} else {
					if (mouseX > radials[i].x - radials[i].w / 2
							&& mouseX < radials[i].x + radials[i].w / 2
							&& mouseY > radials[i].y - radials[i].h / 2
							&& mouseY < radials[i].y + radials[i].h / 2) {

						if (shift && radials[i].selected) {
							radials[i].selected = false;
						}
					}
				}
			}
		}
		renameMode = false;
		if (!massSelection) {
			int length = buttons.length;
			anythingPressed = false;
			for (int i = 0; i < length; i++) {
				buttons[i].rename = false;
				if (mouseX > buttons[i].x
						&& mouseX < buttons[i].x + buttons[i].w
						&& mouseY > buttons[i].y
						&& mouseY < buttons[i].y + buttons[i].h) {
					anythingPressed = true;
					if (!editMode) {
						if (buttons[i].toggle) {
							if (mouseX > buttons[i].x
									&& mouseX < buttons[i].x + buttons[i].w
									&& mouseY > buttons[i].y
									&& mouseY < buttons[i].y + buttons[i].h) {
								if (!buttons[i].on) {
									buttons[i].on = true;
								} else {
									buttons[i].on = false;
									buttons[i].hover = false;
								}
							}
						}
						buttons[i].pressing = true;
						UIActions.buttonAction(i);
					} else {
						if (!buttons[i].selected) {
							massSelection = false;
						}
						if (!option) {
							if (mouseX >= buttons[i].x + buttons[i].w * 6 / 7.
									&& mouseY >= buttons[i].y + buttons[i].h
											* 6 / 7.) {
								buttons[i].resizeSel = true;
							} else {
								if (shift && buttons[i].selected) {
									buttons[i].selected = false;
								} else {
									buttons[i].selected = true;
								}
							}
						} else {
							System.out.println("duplicate");
							buttons = AltMath.incArray(buttons);
							buttons[buttons.length - 1] = new button(this);
							buttons[buttons.length - 1].init(buttons[i].x,
									buttons[i].y, buttons[i].w, buttons[i].h,
									buttons[i].label, buttons[i].toggle);
							buttons[buttons.length - 1].selected = true;
							buttons[i].selected = false;
						}
					}
					buttons[i].display();
				} else {
					if (!shift && !wasSel) {
						buttons[i].selected = false;
						buttons[i].resizeSel = false;
					}
				}
			}
			length = graphs.length;
			for (int i = 0; i < length; i++) {
				graphs[i].rename = false;
				if (mouseX > graphs[i].x - graphs[i]._w / 2
						&& mouseX < graphs[i].x + graphs[i].w + graphs[i]._w
								/ 2
						&& mouseY > graphs[i].y - graphs[i]._h / 2
						&& mouseY < graphs[i].y + graphs[i].h + graphs[i]._h
								/ 2) {
					anythingPressed = true;
					if (!editMode) {
						graphs[i].pressing = true;
						graphs[i].display();
						UIActions.graphAction(i);
					} else {
						if (!option) {
							if (!graphs[i].selected) {
								massSelection = false;
							}
							if (mouseX >= graphs[i].x + graphs[i].w * 6 / 7.
									&& mouseY >= graphs[i].y + graphs[i].h * 6
											/ 7.) {
								graphs[i].resizeSel = true;
							} else {
								if (shift && graphs[i].selected) {
									graphs[i].selected = false;
								} else {
									graphs[i].selected = true;
								}
							}
						} else {
							System.out.println("DUPLICATE");
							graphs = AltMath.incArray(graphs);
							graphs[graphs.length - 1] = new graph(this);
							graphs[graphs.length - 1].init(graphs[i].x,
									graphs[i].y, graphs[i].w, graphs[i].h,
									graphs[i].label, graphs[i].showValues,
									graphs.length - 1);
							graphs[graphs.length - 1].selected = true;
							graphs[i].selected = false;
						}
					}
					graphs[i].display();
				} else {
					if (!shift && !wasSel) {
						graphs[i].selected = false;
						graphs[i].resizeSel = false;
					}
				}
			}
			length = radials.length;
			for (int i = 0; i < length; i++) {
				radials[i].rename = false;
				if (mouseX > radials[i].x - radials[i].w / 2
						&& mouseX < radials[i].x + radials[i].w / 2
						&& mouseY > radials[i].y - radials[i].h / 2
						&& mouseY < radials[i].y + radials[i].h / 2) {
					anythingPressed = true;
					if (!editMode) {
						radials[i].pressing = true;
						radials[i].display();
						UIActions.radialAction(i);
					} else {
						if (!radials[i].selected) {
							massSelection = false;
						}
						if (!option) {
							// if (mouseX >= radials[i].x + radials[i].w * 6 /
							// 14.
							// && mouseY >= radials[i].y + radials[i].h * 6 /
							// 14.) {
							if (mouseX >= radials[i].x + radials[i].w * 4 / 14.
									&& mouseY >= radials[i].y + radials[i].h
											* 4 / 14.) {
								radials[i].resizeSel = true;
							} else {
								if (shift && radials[i].selected) {
									radials[i].selected = false;
								} else {
									radials[i].selected = true;
								}
							}
						} else {
							System.out.println("duplicate");
							radials = AltMath.incArray(radials);
							radials[radials.length - 1] = new radial(this);
							radials[radials.length - 1].init(radials[i].x,
									radials[i].y, radials[i].w, radials[i].h,
									radials[i].label, radials[i].showValues,
									radials.length - 1);
							radials[radials.length - 1].selected = true;
							radials[i].selected = false;
						}
					}
					radials[i].display();
				} else {
					if (!shift && !wasSel) {
						radials[i].selected = false;
						radials[i].resizeSel = false;
					}
				}
			}
			if (!anythingPressed && mousePressed) {
				selection[0] = mouseX;
				selection[2] = 0;
				selection[3] = 0;
				selection[1] = mouseY;
			}
		}
	}

	public void mouseReleased() {

		boolean somethingSel = false;
		for (int i = 0; i < buttons.length; i++) {
			if (buttons[i].selected) {
				somethingSel = true;
			}
		}
		for (int i = 0; i < graphs.length; i++) {
			if (graphs[i].selected) {
				somethingSel = true;
			}
		}
		for (int i = 0; i < radials.length; i++) {
			if (radials[i].selected) {
				somethingSel = true;
			}
		}
		if (!somethingSel) {
			massSelection = false;
		}

		for (int i = 0; i < buttons.length; i++) {
			buttons[i].resizeSel = false;
			if (buttons[i].pressing) {
				buttons[i].pressing = false;
				buttons[i].display();
				if (!buttons[i].toggle) {
					UIActions.buttonAction(i);
				}
			}
		}
		for (int i = 0; i < graphs.length; i++) {
			graphs[i].resizeSel = false;
			if (graphs[i].pressing) {
				graphs[i].pressing = false;
				graphs[i].display();
			}
		}
		for (int i = 0; i < radials.length; i++) {
			radials[i].resizeSel = false;
			if (radials[i].pressing) {
				radials[i].pressing = false;
				radials[i].display();
			}
		}
	}

	void updateGraphs(graph[] graphs) {
		for (int i = 0; i < graphs.length; i++) {
			if (mouseX > graphs[i].x && mouseX < graphs[i].x + graphs[i].w
					&& mouseY > graphs[i].y
					&& mouseY < graphs[i].y + graphs[i].h) {
				if (!graphs[i].hover) {
					graphs[i].hover = true;
				}
			} else if (graphs[i].hover) {
				graphs[i].hover = false;
			}
			graphs[i].display();
		}
	}

	void updateRadials(radial[] radials) {
		for (int i = 0; i < radials.length; i++) {
			if (mouseX > radials[i].x - radials[i].w / 2
					&& mouseX < radials[i].x + radials[i].w / 2
					&& mouseY > radials[i].y - radials[i].h / 2
					&& mouseY < radials[i].y + radials[i].h / 2) {
				if (!radials[i].hover) {
					radials[i].hover = true;
				}
			} else if (radials[i].hover) {
				radials[i].hover = false;
			}
			radials[i].display();
		}
	}

	void updateButtons(button[] buttons) {
		for (int i = 0; i < buttons.length; i++) {
			if (mouseX > buttons[i].x && mouseX < buttons[i].x + buttons[i].w
					&& mouseY > buttons[i].y
					&& mouseY < buttons[i].y + buttons[i].h) {
				if (!buttons[i].hover) {
					buttons[i].hover = true;
				}
			} else if (buttons[i].hover) {
				buttons[i].hover = false;
			}
			buttons[i].display();
		}
	}

	public void text(String string, double dbl1, double dbl2) {
		if (loaded) {
			text(string, (float) (dbl1), (float) (dbl2));
		}
	}

	// arc(x, y, width, height, start, stop)
}
